﻿#include "JsLexer.h"
#include "CodeStyleDef.h"

#if USE_QSCI

#include <Qsci/qsciscintilla.h>
#include <Qsci/qsciapis.h>
#include <QDebug>


QStringList js_keywords = {
    "let", "var", "const", "function", "class", "extends", "super",
    "if", "else", "switch", "case", "default", "for", "while", "do",
    "break", "continue", "return", "try", "catch", "finally", "throw",
    "new", "this", "typeof", "instanceof", "void", "delete", "in",
    "export", "import", "from", "as", "default", "async", "await",
    "true", "false", "null", "undefined", "NaN", "Infinity"
};

QStringList js_functions = {
    // 自定义方法
    "Available", "Exit", "Sleep", "ShowMsg", "SetRetryCnt", "SetRetryTimeout",
    "SendTlv", "SendIIC", "ReadFile", "SelectFile",
    "Toast.info", "Toast.error", "Toast.warning", "Toast.success",

    // JavaScript 内置方法
    "setTimeout", "console.log", "console.error",
    "setInterval", "clearTimeout", "clearInterval", "parseInt",
    "parseFloat", "isNaN", "isFinite", "encodeURI", "decodeURI",
    "encodeURIComponent", "decodeURIComponent", "eval", "Number",
    "String", "Boolean", "Object", "Array", "Function", "Date",
    "RegExp", "Error", "Math.abs", "Math.ceil", "Math.floor",
    "Math.round", "Math.max", "Math.min", "Math.random", "Math.sqrt",
    "JSON.parse", "JSON.stringify"
};

QStringList js_const = {
    // IIC_STATUS
    "IIC_STATUS.NULL", "IIC_STATUS.BUSY", "IIC_STATUS.END_RECEIVE",
    "IIC_STATUS.END_SEND", "IIC_STATUS.ERR_MASTER_NCK",

    // TlvTag
    "TlvTag.Tlv_seq_id", "TlvTag.Tlv_status", "TlvTag.Tlv_reserve", "TlvTag.Tlv_IIC_feedback", "TlvTag.Tlv_IIC_IIC_CALL",
    "TlvTag.Tlv_Interrupt_resp", "TlvTag.Tlv_MCU_RESET", "TlvTag.Tlv_TOUCH_EVENT", "TlvTag.Tlv_MCU_Product_STATUS",
    "TlvTag.Tlv_MCU_Release_TimeStamp", "TlvTag.Tlv_MCU_RAM_Data", "TlvTag.Tlv_MCU_Product_STD_Frame",
    "TlvTag.Tlv_MCU_Product_EXT_Frame", "TlvTag.Tlv_MCU_Product_REC_Frame", "TlvTag.Tlv_MCU_Warning",
    "TlvTag.Tlv_MCU_String", "TlvTag.Tlv_MCU_Dump", "TlvTag.Tlv_MCU_DumpControl", "TlvTag.Tlv_MCU_ROM_Data",
    "TlvTag.Tlv_MCU_BOOT_APP_REQ", "TlvTag.Tlv_MCU_BOOT_APP_RSP", "TlvTag.Tlv_MCU_Program_REQ", "TlvTag.Tlv_MCU_Program_RSP",
    "TlvTag.Tlv_MCU_Enter_BOOT", "TlvTag.Tlv_MCU_CAN_TX_REQ", "TlvTag.Tlv_MCU_CAN_TX_RSP", "TlvTag.Tlv_MCU_CAN_RX",
    "TlvTag.Tlv_MCU_SET_IO", "TlvTag.Tlv_MCU_ADC_REQ", "TlvTag.Tlv_MCU_ADC_RSP", "TlvTag.Tlv_MCU_REQ_RSP",
    "TlvTag.Tlv_PL_IIC_RSP", "TlvTag.Tlv_IntnCall_RSP", "TlvTag.Tlv_PL_IIC_REQ", "TlvTag.Tlv_IntnCall"
};

JsLexer::JsLexer(QObject *parent)
    : QsciLexerJavaScript(parent)
{
    initKeywordsAndApis();
    initFont();
}

void JsLexer::initFont()
{
    QFont baseFont(CodeStyle::codeBaseFont());
    QFont boldFont(baseFont); boldFont.setBold(true);
    QFont italicFont(baseFont); italicFont.setItalic(true);

    setFont(baseFont);

    // 配置表
    QList<CodeStyle> styles = {
        {QsciLexerJavaScript::Keyword,             boldFont,   Qt::darkYellow},
        {QsciLexerJavaScript::Comment,             baseFont,   Qt::darkGreen},
        {QsciLexerJavaScript::CommentLine,         baseFont,   Qt::darkGreen},
        {QsciLexerJavaScript::CommentDoc,          italicFont, Qt::darkGreen},
        {QsciLexerJavaScript::CommentLineDoc,      italicFont, Qt::darkGreen},
        {QsciLexerJavaScript::DoubleQuotedString,  baseFont,   Qt::darkRed},
        {QsciLexerJavaScript::SingleQuotedString,  baseFont,   Qt::darkRed},
        {QsciLexerJavaScript::Number,              baseFont,   Qt::darkBlue},
        {QsciLexerJavaScript::Regex,               baseFont,   Qt::darkRed},
        {QsciLexerJavaScript::Identifier,          baseFont,   Qt::darkCyan},
        {QsciLexerJavaScript::Operator,            baseFont,   Qt::black},
        {QsciLexerJavaScript::GlobalClass,         baseFont,   Qt::darkMagenta}
    };

    // 应用配置
    for (const auto &s : styles) {
        setFont(s.font, s.type);
        setColor(s.color, s.type);
    }
}

void JsLexer::initKeywordsAndApis()
{
    QsciAPIs* apis = new QsciAPIs(this);
    // 添加一些 API（可以自己扩展，比如 DOM、ES6 API 等）
    for (QString& s : js_functions) {
        apis->add(s);
    }

    for (QString& s : js_const) {
        apis->add(s);
    }

    for (QString& s : js_keywords) {
        apis->add(s);
    }

    // 编译 API 列表
    apis->prepare();
}

const char *JsLexer::keywords(int set) const
{
    if (set == 1) {
        return js_keywords.join(" ").toLatin1();
    }
    return "";
}

#endif // USE_QSCI
